import random
import string
from PIL import Image, ImageFont, ImageDraw, ImageFilter
import os


class ImageVerify:
    def __init__(self, width=140, height=40, length=4, size=28):
        """
        初始化
        :param width:图片高度
        :param height:图片宽度
        :param length:字符长度
        :param size:字体大小
        """
        self.width = width
        self.height = height
        self.length = length
        self.size = size

    def random_str(self):
        """
        定义生成随机字符串的方法：10个数字26个大小写字母
        :return:随机字符串
        """
        source = string.ascii_letters + string.digits  # 26个大小写字母+10个数字
        return ''.join(random.sample(source, self.length))

    def random_color(self, start=0, end=255):
        """
        随机颜色RGB
        :param start:起始值
        :param end:结束值
        :return:tuple(r,g,b)
        """
        res = [random.randint(0, 255) for i in range(3)]
        return tuple(res)

    def random_lines(self, draw):
        """
        绘制干扰线，两点决定一条线，一个点由（x，y）坐标决定
        :param draw:画笔对象
        :return:
        """
        for i in range(self.length):  # 确定画几条线
            # 第1个random生成坐标x，第2个random生成坐标y，循环2次生成一个点（两点为一直线），上面的for循环生成self.length条线
            lines = [(random.randint(0, self.width), random.randint(0, self.height)) for i in range(2)]
            # 用画笔将随机生成的两点，用fill颜色连成一条2px的线
            draw.line(list(lines), fill=self.random_color(start=100), width=2)

    def random_points(self, draw, rate):
        """
        绘制干扰点（x,y）
        :param draw:画笔对象
        :param rate:出现频率
        :return:
        """
        for x in range(self.width):  # X轴的值
            for y in range(self.height):  # Y轴的值
                if random.randint(1, 100) <= rate:  # 控制频率，只有满足条件，才用fill颜色画点
                    draw.point((x, y), fill=self.random_color(start=150))

    def image_code(self):
        """
        生成验证码图片
        :return:
        """
        # 创建Image画布对象，三原色，设置长和高，背景颜色（255,255,255，是白色）
        image = Image.new('RGB', (self.width, self.height), (255, 255, 255))

        # 创建Font字体对象
        file = os.path.dirname(os.path.abspath(__file__))  # 括号内是当前文件的绝对路径，用dirname括起来是只要文件夹的路径
        font = ImageFont.truetype(f'{file}/HYYakuHei-85W.ttf', self.size)  # 参数一是字体路径，参数二是字体大小

        # 创建draw画笔对象
        draw = ImageDraw.Draw(image)

        # 生成随机字符串
        code = self.random_str()

        # 将生成的随机字符串画上画布
        for t in range(self.length):
            # 将验证码中每个字符，从text指定的坐标开始，code方法，用font字体，fill颜色画出来，生成self.length个字符
            draw.text((30 * t + 16, 1), code[t], font=font, fill=self.random_color(end=200))
        # 用画笔画干扰线
        self.random_lines(draw)

        # 用画笔画干扰点
        self.random_points(draw, 20)

        # 图片模糊滤波处理，直接调用自带的模糊滤波
        # image = image.filter(ImageFilter.BLUR)
        print('验证码:', code)
        return image, code

# if __name__ == '__main__':
#     imgVerify = ImageVerify()
#     img = imgVerify.image_code()
#     with open('test.png', 'wb') as f:
#         img.save(f)
